<?php
/***
 *
 * 发送通知消息
 *
 */

namespace App\Http\Services\Message;

use App\Http\Model\Hint;
use Illuminate\Http\Request;
use phpDocumentor\Reflection\Types\Context;
use vendor\project\StatusTest;

class MessageServices
{
    private $WebHook = ''; //webhook 地址

    const EXCEPTION_URL_TEST = "https://hooks.slack.com/services/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"; //测试环境
    const EXCEPTION_URL_PROD = "https://hooks.slack.com/services/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"; //生产环境

    public function __construct($WebHook)
    {
        $this->WebHook = $WebHook;
    }

    /**
     * 发送错误警报
     * @param Request $request
     * @param \Exception $exception
     * @return void
     */
    public static function sendException(Request $request, \Exception $exception)
    {

	return;

        //本地环境不报警
        if (env('APP_ENV') == 'local') {
            return;
        }

        //白名单
        if (self::whiteList($request, $exception) == false) {
            return;
        }

        $isCli = isCli() ? '-cli' : '';
        $traceId = time() . rand(1000000, 9999999);
        $date = date("Y-m-d H:i:s");

        //trace信息过大，不发送飞书，写入文件日志，需要查询trace时用traceId查询文件日志
        $log = [
            'traceId' => $traceId,
            'time' => $date,
            'message' => $exception->getMessage(),
            'line' => $exception->getLine(),
            'file' => $exception->getFile(),
            'code' => $exception->getCode(),
            'request' => $request->all(),
            'trace' => $exception->getTraceAsString(),
        ];

        write_log("exceptionLog" . $isCli, 'exceptionTrace', $log);


        //发送到飞书
        $msg = [
            "【甜枕 API服务报错】",
            "[time] " . $date,
            "[message] " . $exception->getMessage(),
            "[line] " . $exception->getLine(),
            "[file] " . $exception->getFile(),
            "[code] " . $exception->getCode(),
            "[request] " . json_encode($request->all(), JSON_UNESCAPED_UNICODE),
            "[traceId] " . $traceId,
        ];

        $content = json_encode([
                'text' => implode("\n", $msg)
            ]);

        try {
            $url = env('APP_ENV') != 'product' ? self::EXCEPTION_URL_TEST : self::EXCEPTION_URL_PROD;
            curl_request($url, $content, 'plain');
        } catch (\Exception $e) {
            write_log("exceptionLog_" . $isCli, "报警报错", ['url' => $url, 'msg' => $e->getMessage()]);
        }
    }

    /**
     * 发送消息
     * @param string $text 报警文本
     * @param string $type 报警类型
     * @param mixed $extra 参数数据体
     * @return void
     */
    public static function sendInfo($text, $type = 'info', $extra = [])
    {

        //本地环境不报警
        if (env('APP_ENV') == 'local') {
            return;
        }

        $date = date("Y-m-d H:i:s");

        switch ($type) {
            case "info":
                $tip = "通知";
                break;
            case "warn":
                $tip = "警告";
                break;
            case "error":
                $tip = "错误";
                break;
            default:
                $tip = $type;
        }

        //发送到飞书
        if (is_array($extra) || is_object($extra)) {
            $extra = json_encode($extra, JSON_UNESCAPED_UNICODE);
        }
        $msg = [
            "【甜枕 API服务" . $tip . "】",
            "[time] " . $date,
            "[message] " . $text,
            "[extra] " . $extra,
        ];

        $content = json_encode([
            'msg_type' => 'text',
            'content' => [
                'text' => implode("\n", $msg)
            ]
        ]);

        try {
            $url = env('APP_ENV') != 'product' ? self::EXCEPTION_URL_TEST : self::EXCEPTION_URL_PROD;
            curl_request($url, $content, 'plain');
        } catch (\Exception $e) {
            $isCli = isCli() ? '-cli' : '';
            $isCli = isCli() ? '-cli' : '';
            write_log("exceptionLog_" . $isCli, "报警报错", ['url' => $url, 'msg' => $e->getMessage()]);
        }
    }

    private function text($params)
    {
        $msg = next($params);

        $content = '{"msg_type":"text","content":{"text":"' . $msg . '"}}';
        return curl_request($this->WebHook, $content, 'plain');
    }

    /**
     * 发送消息
     * @param params.1  webhoot
     * @param params.2  msg 消息
     * @return
     */
    public static function __callStatic($method, $params)
    {
        $code = Hint::SUCCESS;
        $msg = Hint::getErrCodeMsg($code);
        $data = [];
        try {

            $WebHook = reset($params);
            if (empty($WebHook)) {
                throw new \Exception('机器人通知消息地址错误');
            }
            $ifOpen = config('message.ifOpen');
            if (!$ifOpen) {
                throw new \Exception('机器人通知消息未开启');
            }

            $object = new self($WebHook);
            $data = $object->$method($params);
            if (isset($data['code']) && $data['code']) {
                throw new \Exception('机器人通知消息发送错误');
            }

        } catch (\Exception $e) {
            $msg = $e->getMessage();
            $code = Hint::ERROR;
        }
        return compact('code', 'msg', 'data');
    }


    /**
     * 报警白名单
     * 已知错误禁止报警的写在这里
     *
     * @param Request $request
     * @param \Exception $exception
     * @return bool true报警 false不报警
     */
    private static function whiteList(Request $request, \Exception $exception)
    {
        $params = $request->all();
        $path = $params['_url'] ?? "";

        //忽略 SQLSTATE[22003]: Numeric value out of range: 1690 BIGINT UNSIGNED value is out of range in '(`kkaudio`.`zb_finance_wallet`.`diamond_balance` + -(100))' (SQL: update `zb_finance_wallet` set `diamond_balance` = `diamond_balance` + -100, `change_timestamp` = 1672225075 where (`user_id` = 2205991))
        $err1690Path = [
            "/counter/gift/give",
            "/mine/exchange",
            "/counter/box/give",
        ];
        if ($exception->getCode() == 22003 && in_array($path, $err1690Path, true)) {
            return false;
        }

        //忽略 SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction (SQL: update `zb_finance_wallet` set `charm_balance` = `charm_balance` + 20, `change_timestamp` = 1672893075 where `user_id` = 1398595)
        $err1213Path = [
            "/counter/box/give",
        ];
        if ($exception->getCode() == 40001 && in_array($path, $err1213Path, true)) {
            return false;
        }

        return true;
    }

}
